package com.rajaev.dtu.tractor.domain.repository.redis;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil;
import com.google.common.collect.Lists;
import com.rajaev.dtu.tractor.domain.entity.DeviceFaultRecord;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Repository;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.Set;

@Repository
public class FaultCodeRedisRepository {

    @Autowired
    RedisTemplate redisTemplate;

    private static String KEY_PREFIX = "DEVICE:FAULT";

    private static String tickTimeField = "tickTime";

    public boolean isFaultSaved(String vin, String faultCode) {
        Object refreshTime = redisTemplate.opsForHash().get(getRedisKey(vin), faultCode);
        if (refreshTime == null) {
            return false;
        }else {
            DeviceFaultRecord deviceFaultRecord = new DeviceFaultRecord();
            deviceFaultRecord.setCode(faultCode);
            deviceFaultRecord.setFaultRefreshTimestamp((Long) refreshTime);
            return deviceFaultRecord.isNotOver();
        }

    }

    public void refreshFaultCode(String vin, String faultCode, long refreshTimeStamp) {
        redisTemplate.opsForHash().put(getRedisKey(vin), faultCode, String.valueOf(refreshTimeStamp));
    }

    /**
     * 清除设备所有的故障
     *
     * @param vin
     */
    /*public void clearDeviceFault(String vin) {
        redisTemplate.delete(getRedisKey(vin));
    }*/

    public List<DeviceFaultRecord> getDeviceFault(String vin) {
        Set<String> hks = redisTemplate.opsForHash().keys(getRedisKey(vin));
        List<String> hkList = Lists.newArrayList(hks);
        List<String> hvList = redisTemplate.opsForHash().multiGet(getRedisKey(vin), hkList);
        List<DeviceFaultRecord> deviceFaultRecordList = new ArrayList<>();

        for (int i = 0; i < hkList.size(); i++) {
            DeviceFaultRecord deviceFaultRecord = new DeviceFaultRecord();
            deviceFaultRecord.setCode(hkList.get(i));
            deviceFaultRecord.setFaultRefreshTimestamp(Long.parseLong(hvList.get(i)));
            if (!deviceFaultRecord.isNotOver()) {
                deviceFaultRecordList.add(deviceFaultRecord);
            }
        }

        return deviceFaultRecordList;
    }

    /**
     * 清除设备所有的故障
     * @param vin
     */
    public void clearDeviceFault(String vin) {
        redisTemplate.delete(getRedisKey(vin));
    }

    public Optional<DeviceFaultRecord> getDeviceFault(String vin,String code) {
        Object refreshTime =  redisTemplate.opsForHash().get(getRedisKey(vin),code);
        if(refreshTime == null){
            return Optional.empty();
        }else {
            DeviceFaultRecord deviceFaultRecord = new DeviceFaultRecord();
            deviceFaultRecord.setCode(code);
            deviceFaultRecord.setFaultRefreshTimestamp(Convert.toLong(refreshTime));
            return Optional.of(deviceFaultRecord);
        }
    }

    public void deleteDeviceFaultFromRedis(String vin, String faultCode) {
        redisTemplate.opsForHash().delete(getRedisKey(vin), faultCode);
    }

    /**
     * 清理长时间没有刷新的故障，认为该故障已经解除
     */
    @Scheduled(fixedRate = 60 * 1000)
    public void clearTimeoutFault() {
        Set<String> keys = redisTemplate.keys(KEY_PREFIX + "*");
        List<String> keyList = Lists.newArrayList(keys);
        keyList.forEach(key -> {
            String vin = key.replace(KEY_PREFIX, "");
            List<DeviceFaultRecord> list = getDeviceFault(vin);
            list.forEach(deviceFaultRecord -> {
                if (!deviceFaultRecord.isNotOver()) {
                    deleteDeviceFaultFromRedis(vin, deviceFaultRecord.getCode());
                }
            });
        });
    }

    private String getRedisKey(String deviceNo) {
        return KEY_PREFIX.concat(StrUtil.COLON).concat(deviceNo);
    }
}
